package com.apobates.forum.toro.proxy.strategy;

import com.apobates.forum.toro.proxy.MapperMultiAttrStatements;
import com.apobates.forum.toro.utils.BeanHelper;
import com.apobates.forum.toro.utils.CommonHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
/**
 * 抽像的Proxy Supply One/Many 聚合属性执行器
 * 子实现类: ProxyQueryExecutor,ProxySupplyExecutor,ProxySupplyManyExecutor
 * @param <E> 最终聚合对象的类型
 *
 * @author xiaofanku@live.cn
 * @since 20220517
 */
public abstract class AbstractProxyStrategy<E> {
    private final static Logger logger = LoggerFactory.getLogger(AbstractProxyStrategy.class);
    /**
     * 标识子类的名称
     * @return
     */
    protected abstract String getSentinel();

    // key=设置的属性名称, value=设置的属性值
    protected Map<String,Object> collectRelateObj(
            E targetObj,
            Map<String, MapperMultiAttrStatements.Argument> targetAttrMap,
            Map<String, Collection<Object>> rawSource) {
        // key = selectAttr, value = joinAttrType
        Map<String, String> attrTypeMap = targetAttrMap.values().stream().collect(Collectors.toMap(arg->arg.getSelectAttr(), arg->arg.getJoinAttrTypeName()));
        // key = selectAttr, value = selectAttrVal
        Map<String, Object> queryAttrValMap = new HashMap<>();
        try{
            queryAttrValMap = BeanHelper.getMultiAttrVal(targetObj, attrTypeMap);
        }catch (Exception e){
            String bbb = String.format("[MSMS][%s]query match join argument,error: %s", getSentinel(), e.getMessage());
            logger.debug(bbb);
        }
        // 3)收集设置的属性及值
        Map<String,Object> setAttrValMap = new HashMap<>();
        for(String selectAttr : queryAttrValMap.keySet()) {
            Object expectVal = queryAttrValMap.get(selectAttr);
            MapperMultiAttrStatements.Argument args = targetAttrMap.get(selectAttr);
            if(!args.isTargetAttrSet()) {
                Optional setAttrVal = CommonHelper.seekFirstEle(
                        rawSource.get(args.getTargetAttr()),
                        args.getJoinAttr(),
                        args.getJoinAttrTypeName(),
                        expectVal);
                setAttrValMap.put(args.getTargetAttr(), setAttrVal.orElse(null));
            }else{
                try {
                    Collection setAttrVal = CommonHelper.seekAnyEle(
                        rawSource.get(args.getTargetAttr()),
                        args.getJoinAttr(),
                        expectVal,
                        Class.forName(args.getCollectionType()));
                    setAttrValMap.put(args.getTargetAttr(), setAttrVal);
                }catch (Exception e){
                    String ccc = String.format("[MSMS][%s]seek element collect,error: %s", getSentinel(), e.getMessage());
                    logger.debug(ccc);
                }
            }
        }
        return setAttrValMap;
    }
}
